from rest_framework import status
from rest_framework.views import APIView
from django.http import JsonResponse
from captcha.image import ImageCaptcha
import base64
import io
import random
import redis
import uuid
import jwt  # PyJWT
from django.conf import settings
from datetime import datetime, timedelta

from allmodels.models import SysUser  # 假设用户模型现在在 allmodels.models 中

# 配置Redis连接
redis_client = redis.StrictRedis(host='127.0.0.1', port=6379, db=1, decode_responses=True)

# 在 settings 中配置 JWT 设置
# 例如:
# JWT_SECRET_KEY = 'your_secret_key'
# JWT_ALGORITHM = 'HS256'
# JWT_ACCESS_TOKEN_EXPIRATION = timedelta(minutes=15)  # 访问令牌有效期
# JWT_REFRESH_TOKEN_EXPIRATION = timedelta(days=7)  # 刷新令牌有效期

def generate_access_token(user):
    """生成访问令牌"""
    expiration = datetime.utcnow() + settings.JWT_ACCESS_TOKEN_EXPIRATION
    payload = {
        'user_id': user.id,
        'username': user.username,
        'create_time': user.create_time.isoformat(),  # 使用 create_time
        'exp': expiration,
        'iat': datetime.utcnow()
    }
    # 生成访问令牌
    token = jwt.encode(payload, settings.JWT_SECRET_KEY, algorithm=settings.JWT_ALGORITHM)
    return token


def verify_token(token):
    """验证 JWT 令牌"""
    try:
        # 解码令牌，并返回 payload
        payload = jwt.decode(token, settings.JWT_SECRET_KEY, algorithms=[settings.JWT_ALGORITHM])
        return payload
    except jwt.ExpiredSignatureError:
        # 令牌过期
        return {'error': 'Token expired'}
    except jwt.InvalidTokenError:
        # 令牌无效
        return {'error': 'Invalid token'}

class GetCaptchaView(APIView):
    def get(self, request, *args, **kwargs):
        # 1. 生成随机验证码
        captcha_text, answer = self.generate_random_captcha()

        # 2. 生成一个唯一的 captchaKey（用于存储到 Redis 中）
        captcha_key = str(uuid.uuid4()).replace('-', '')

        # 3. 将答案存入 Redis，设置过期时间为120秒
        redis_client.setex(captcha_key, 120, answer)

        # 4. 生成验证码图片
        image_captcha = ImageCaptcha()
        captcha_image = image_captcha.generate_image(captcha_text)

        # 5. 将验证码图片转为 Base64 格式
        buffered = io.BytesIO()
        captcha_image.save(buffered, format="PNG", optimize=True, quality=50)
        img_str = base64.b64encode(buffered.getvalue()).decode('utf-8')

        # 6. 将Base64编码前缀拼接为Data URI格式
        captcha_base64 = f"data:image/png;base64,{img_str}"

        # 7. 返回JSON响应，包含captchaKey和Base64编码的图片
        return JsonResponse({
            'code': '00000',
            'data': {
                'captchaKey': captcha_key,
                'captchaBase64': captcha_base64
            },
            'msg': '一切ok'
        }, status=200)

    def generate_random_captcha(self):
        # 生成随机验证码，包括数字和加减乘除操作
        operators = ["+", "-", "*", "/"]
        captcha_text = ""

        # 生成两个随机数字
        num1 = random.randint(0, 9)
        num2 = random.randint(0, 9)
        answer = None

        # 随机选择一个操作符
        operator = random.choice(operators)

        # 根据操作符生成验证码及答案
        if operator == "+":
            captcha_text = f"{num1} + {num2}"
            answer = num1 + num2
        elif operator == "-":
            captcha_text = f"{num1} - {num2}"
            answer = num1 - num2
        elif operator == "*":
            captcha_text = f"{num1} * {num2}"
            answer = num1 * num2
        elif operator == "/":
            # 避免除法出现小数，确保整除
            num1 = random.randint(1, 9)
            num2 = random.randint(1, 9)
            captcha_text = f"{num1 * num2} / {num2}"
            answer = num1

        return captcha_text, answer

class LoginView(APIView):
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        captcha_key = request.data.get('captchaKey')
        captcha_code = request.data.get('captchaCode')

        # 校验验证码
        if not captcha_key or not captcha_code:
            return JsonResponse({
                'code': '10001',
                'msg': '验证码不完整'
            }, status=status.HTTP_400_BAD_REQUEST)

        # 从 Redis 获取正确的验证码答案
        correct_answer = redis_client.get(captcha_key)

        # 验证码过期或错误
        if not correct_answer or correct_answer != captcha_code:
            return JsonResponse({
                'code': '10002',
                'msg': '验证码错误或已过期'
            }, status=status.HTTP_400_BAD_REQUEST)

        # 验证用户名和密码
        try:
            user = SysUser.objects.get(username=username)  # 使用 SysUser 代替 User
            if user.check_password(password):
                # 登录成功，删除 Redis 中的验证码
                redis_client.delete(captcha_key)

                # 生成访问令牌和刷新令牌
                access_token = generate_access_token(user)
                refresh_token = generate_access_token(user)

                return JsonResponse({
                    'code': '00000',
                    'msg': '登录成功',
                    'data': {
                        'accessToken': access_token,
                        'expires': settings.JWT_ACCESS_TOKEN_EXPIRATION.total_seconds() * 1000,
                        'refreshToken': refresh_token,
                        'tokenType': 'Bearer'
                    }
                }, status=status.HTTP_200_OK)
            else:
                return JsonResponse({
                    'code': '10003',
                    'msg': '用户名或密码错误'
                }, status=status.HTTP_400_BAD_REQUEST)
        except SysUser.DoesNotExist:  # 使用 SysUser 代替 User
            return JsonResponse({
                'code': '10003',
                'msg': '用户名或密码错误'
            }, status=status.HTTP_400_BAD_REQUEST)


class LogoutView(APIView):
    def delete(self, request):
        # 获取 Authorization 令牌
        auth_header = request.headers.get('Authorization')
        if not auth_header or not auth_header.startswith('Bearer '):
            return JsonResponse({
                'code': '10004',
                'msg': '无效的令牌'
            }, status=401)

        access_token = auth_header.split(' ')[1]  # 获取实际的 JWT 令牌

        # 验证令牌有效性
        payload = verify_token(access_token)
        if 'error' in payload:
            return JsonResponse({
                'code': '10005',
                'msg': '令牌验证失败'
            }, status=401)

        # 执行注销逻辑（可根据具体情况处理，比如删除/无效化token）
        # 清理用户会话或其他数据

        # 返回注销成功的响应
        return JsonResponse({
            'code': '00000',
            'data': {},
            'msg': '注销成功'
        }, status=200)